import random
from typing import List


class LoadBalancer:
    """
    实现三种常见负载均衡算法的类：
    1. 轮询 (Round Robin)
    2. 随机选择 (Random)
    3. 加权轮询 (Weighted Round Robin)
    """

    def __init__(self, servers: List[str]):
        """
        初始化负载均衡器

        :param servers: 服务器列表，例如 ['server1.com', 'server2.com', 'server3.com']
        """
        self.servers = servers
        self.server_count = len(servers)
        self.current_index = 0  # 用于轮询算法

    def round_robin(self) -> str:
        """
        轮询算法：按顺序依次选择服务器

        :return: 选中的服务器地址
        """
        if not self.servers:
            raise Exception("没有可用的服务器")

        server = self.servers[self.current_index]
        self.current_index = (self.current_index + 1) % self.server_count
        return server

    def random_selection(self) -> str:
        """
        随机选择算法：随机选择一个服务器

        :return: 随机选中的服务器地址
        """
        if not self.servers:
            raise Exception("没有可用的服务器")

        return random.choice(self.servers)

    def weighted_round_robin(self, weights: List[int]) -> str:
        """
        加权轮询算法：根据权重选择服务器

        :param weights: 与服务器列表对应的权重列表
        :return: 根据权重选中的服务器地址
        """
        if not self.servers:
            raise Exception("没有可用的服务器")

        if len(weights) != self.server_count:
            raise Exception("权重列表的长度必须与服务器列表的长度相同")

        # 计算总权重
        total_weight = sum(weights)
        if total_weight <= 0:
            raise Exception("总权重必须为正数")

        # 生成随机数并根据权重选择服务器
        rand_num = random.randint(1, total_weight)

        for i, weight in enumerate(weights):
            rand_num -= weight
            if rand_num <= 0:
                return self.servers[i]

        # 如果由于浮点数精度问题没有返回，则返回最后一个服务器
        return self.servers[-1]


# 使用示例
if __name__ == "__main__":
    # 初始化服务器列表
    servers = ['server1.com', 'server2.com', 'server3.com']
    lb = LoadBalancer(servers)

    print("轮询算法示例:")
    for i in range(5):
        print(f"第{i + 1}次选择: {lb.round_robin()}")

    print("\n随机选择算法示例:")
    for i in range(5):
        print(f"第{i + 1}次选择: {lb.random_selection()}")

    print("\n加权轮询算法示例:")
    weights = [1, 2, 3]  # server3.com 被选中的概率最高
    for i in range(10):
        print(f"第{i + 1}次选择: {lb.weighted_round_robin(weights)}")
